﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using Assist;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using DataBase;
using DBService;
using YArchitech.Revit.RevitExtension;

namespace YArchitech.Revit.MEP.Opening
{
	public class DbBeamToBeOpened : DbOpeningBase, IDbObject
	{
		public DbBeamToBeOpened(int projectId, XYZ basePt, int beamId, int pipeId, SectionParameter sp, BoxParameter bp, CutType cType, HostType hType, string level)
		{
			this.mGuid = Guid.NewGuid();
			this.mProjectId = projectId;
			this.mHostId = beamId;
			this.mPt = basePt;
			this.mParameter = sp;
			base.BoxParameter = bp;
			base.CutType = cType;
			base.HostType = hType;
			base.Level = level;
			base.Date = DateTime.Now;
			base.IsCurrentProject = true;
			this.mPipeId = pipeId;
		}

		public override void WirteToXML(string fileName)
		{
			XmlUtils.AddBeamOpening(fileName, this);
		}

		public static List<DbBeamToBeOpened> ReadFromXML(string fileName)
		{
			return XmlUtils.ReadBeamOpening(fileName);
		}

		public static DbBeamToBeOpened ReadFromXML(Guid id, string fileName)
		{
			return XmlUtils.ReadBeamOpening(id, fileName);
		}

		public override void UpdateToXML(string fileName)
		{
			XmlUtils.UpdateBeamOpeningToXML(fileName, this);
		}

		public static List<DbBeamToBeOpened> GetByProject(DbProject project)
		{
			List<DbBeamToBeOpened> result;
			try
			{
				if (project.Database.Connection.State == ConnectionState.Closed)
				{
					project.Database.Connection.Open();
				}
				List<DbBeamToBeOpened> list = new List<DbBeamToBeOpened>();
				string sql = string.Format("SELECT ProjectId,HostId,PtX,PtY,PtZ,Parameter1,Parameter2,SectionType,Guid,Status,BoxParameter1,BoxParameter2,BoxParameter3,BoxParameter4,Level,CutType,HostType,BoxSectionType,Remark,PipeId FROM tbSynergyOpiening WHERE ProjectId={0} and HostType=3", project.Id);
				DataTable dataTable = project.Database.ExecQuery(sql);
				if (project.Database.Connection.State == ConnectionState.Open)
				{
					project.Database.Connection.Close();
				}
				if (dataTable == null)
				{
					result = null;
				}
				else
				{
					for (int i = 0; i < dataTable.Rows.Count; i++)
					{
						int projectId = Convert.ToInt32(dataTable.Rows[i]["ProjectId"]);
						Guid mGuid = Guid.Parse(dataTable.Rows[i]["Guid"].ToString());
						int beamId = Convert.ToInt32(dataTable.Rows[i]["HostId"]);
						int pipeId = Convert.ToInt32(dataTable.Rows[i]["PipeId"]);
						OpeningStatus status = (OpeningStatus)dataTable.Rows[i]["Status"];
						XYZ basePt = new XYZ(Convert.ToDouble(dataTable.Rows[i]["PtX"]), Convert.ToDouble(dataTable.Rows[i]["PtY"]), Convert.ToDouble(dataTable.Rows[i]["PtZ"]));
                        DBService.SectionType sectionType = (DBService.SectionType)Convert.ToInt32(dataTable.Rows[i]["SectionType"]);
						SectionParameter sp = null;
                        if (sectionType == DBService.SectionType.Arc)
						{
							sp = new SectionParameter(Convert.ToDouble(dataTable.Rows[i]["Parameter1"]));
						}
                        else if (sectionType == DBService.SectionType.Rect)
						{
							double param = Convert.ToDouble(dataTable.Rows[i]["Parameter1"]);
							double param2 = Convert.ToDouble(dataTable.Rows[i]["Parameter2"]);
							sp = new SectionParameter(param, param2);
						}
                        DBService.SectionType sectionType2 = (DBService.SectionType)Convert.ToInt32(dataTable.Rows[i]["BoxSectionType"]);
						BoxParameter bp = null;
                        if (sectionType2 == DBService.SectionType.Arc)
						{
							bp = new BoxParameter(Convert.ToDouble(dataTable.Rows[i]["BoxParameter1"]));
						}
                        else if (sectionType2 == DBService.SectionType.Rect)
						{
							double param3 = Convert.ToDouble(dataTable.Rows[i]["BoxParameter1"]);
							double param4 = Convert.ToDouble(dataTable.Rows[i]["BoxParameter1"]);
							double param5 = Convert.ToDouble(dataTable.Rows[i]["BoxParameter3"]);
							double param6 = Convert.ToDouble(dataTable.Rows[i]["BoxParameter4"]);
							bp = new BoxParameter(param3, param4, param5, param6);
						}
						CutType cType = (CutType)Convert.ToInt32(dataTable.Rows[i]["CutType"]);
						HostType hType = (HostType)Convert.ToInt32(dataTable.Rows[i]["HostType"]);
						string level = Convert.ToString(dataTable.Rows[i]["Level"]);
						string remark = Convert.ToString(dataTable.Rows[i]["Remark"]);
						list.Add(new DbBeamToBeOpened(projectId, basePt, beamId, pipeId, sp, bp, cType, hType, level)
						{
							Remark = remark,
							mGuid = mGuid,
							mDatabase = project.Database,
							Status = status
						});
					}
					result = list;
				}
			}
			catch (Exception ex)
			{
				if (project.Database.Connection.State == ConnectionState.Open)
				{
					project.Database.Connection.Close();
				}
				throw ex;
			}
			return result;
		}

		public override void AddOpeningTag(UIApplication uiApp, TagStyle ts)
		{
		}

		private static Transform getBeamTransform(XYZ origin, FamilyInstance beam)
		{
			Transform identity = Transform.Identity;
			Line line = (beam.Location as LocationCurve).Curve as Line;
			if (line == null)
			{
				return identity;
			}
			identity.Origin = origin;
			identity.BasisX = (line.GetEndPoint(1) - line.GetEndPoint(0)).Normalize();
			identity.BasisY = XYZ.BasisZ.Normalize();
			identity.BasisZ = identity.BasisX.CrossProduct(identity.BasisY);
			return identity;
		}

		private static XYZ getTransformX(FamilyInstance beam)
		{
			Line line = (beam.Location as LocationCurve).Curve as Line;
			if (line == null)
			{
				return null;
			}
			return (line.GetEndPoint(1) - line.GetEndPoint(0)).Normalize();
		}

		public override Element Create(UIApplication app)
		{
            Autodesk.Revit.DB.Opening opening = this.create(app);
			if (opening != null)
			{
				base.SetDate(opening);
				base.Status = OpeningStatus.Opened;
			}
			return opening;
		}

        private Autodesk.Revit.DB.Opening create(UIApplication app)
		{
            Autodesk.Revit.DB.Opening result = null;
			Document document = app.ActiveUIDocument.Document;
			Transaction transaction = new Transaction(document, "CreateOpening");
			try
			{
				transaction.Start();
				Element element = DbOpeningBase.FindTag(this, document);
				if (element != null)
				{
					document.Delete(element.Id);
				}
				FamilyInstance familyInstance = RevitVersionFuncs.GetElement(document, new ElementId(this.mHostId)) as FamilyInstance;
				Transform beamTransform = DbBeamToBeOpened.getBeamTransform(this.mPt, familyInstance);
				CurveArray curveArray = new CurveArray();
                if (base.BoxParameter.SectionType == DBService.SectionType.Rect)
				{
					double num = AssistFunc.mmToFeet(base.OpeningParameter.Parameter4);
					double num2 = AssistFunc.mmToFeet(base.OpeningParameter.Parameter3);
					double num3 = AssistFunc.mmToFeet(base.OpeningParameter.Parameter2);
					double num4 = AssistFunc.mmToFeet(base.OpeningParameter.Parameter1);
					XYZ xyz = DbOpeningBase.TransformPoint(new XYZ(num, num4, 0.0), beamTransform);
					XYZ xyz2 = DbOpeningBase.TransformPoint(new XYZ(num, -num3, 0.0), beamTransform);
					XYZ xyz3 = DbOpeningBase.TransformPoint(new XYZ(-num2, -num3, 0.0), beamTransform);
					XYZ xyz4 = DbOpeningBase.TransformPoint(new XYZ(-num2, num4, 0.0), beamTransform);
					Line line = YJKLineEx.YJKGetBound(xyz, xyz2);
					Line line2 = YJKLineEx.YJKGetBound(xyz2, xyz3);
					Line line3 = YJKLineEx.YJKGetBound(xyz3, xyz4);
					Line line4 = YJKLineEx.YJKGetBound(xyz4, xyz);
					curveArray.Append(line);
					curveArray.Append(line2);
					curveArray.Append(line3);
					curveArray.Append(line4);
				}
				else
				{
					double radius = AssistFunc.mmToFeet(base.OpeningParameter.Parameter1);
					Arc arc = document.CreatYJKArc(this.mPt, radius, 0.0, Math.PI*2, DbBeamToBeOpened.getTransformX(familyInstance), XYZ.BasisZ.Normalize());
					arc.MakeUnbound();
					curveArray.Append(arc);
				}
				result = document.Create.NewOpening(familyInstance, curveArray, (Autodesk.Revit.Creation.eRefFace)4);
				transaction.Commit();
			}
			catch (Exception)
			{
				transaction.RollBack();
			}
			return result;
		}

		public static DbBeamToBeOpened GetFromDB(Guid id, BimServerDB db)
		{
			DbBeamToBeOpened result;
			try
			{
				if (db.Connection.State == ConnectionState.Closed)
				{
					db.Connection.Open();
				}
				DbCommand dbCommand = db.Connection.CreateCommand();
				dbCommand.CommandText = string.Format("SELECT ProjectId,HostId,PtX,PtY,PtZ,Parameter1,Parameter2,SectionType,Guid,Status,BoxParameter1,BoxParameter2,BoxParameter3,BoxParameter4,Level,CutType,HostType,BoxSectionType,Remark,PipeId FROM tbSynergyOpiening WHERE Guid={0} and HostType=3", "@id");
				SqlParameter sqlParameter = new SqlParameter("@id", SqlDbType.UniqueIdentifier);
				sqlParameter.Value = id;
				dbCommand.Parameters.Add(sqlParameter);
				IDataReader dataReader = dbCommand.ExecuteReader();
				DataTable dataTable = db.DataReaderToDataTable(dataReader);
				dataReader.Dispose();
				if (db.Connection.State == ConnectionState.Open)
				{
					db.Connection.Close();
				}
				if (dataTable == null)
				{
					result = null;
				}
				else
				{
					int projectId = Convert.ToInt32(dataTable.Rows[0]["ProjectId"]);
					int beamId = Convert.ToInt32(dataTable.Rows[0]["HostId"]);
					int pipeId = Convert.ToInt32(dataTable.Rows[0]["PipeId"]);
					OpeningStatus status = (OpeningStatus)dataTable.Rows[0]["Status"];
					XYZ basePt = new XYZ(Convert.ToDouble(dataTable.Rows[0]["PtX"]), Convert.ToDouble(dataTable.Rows[0]["PtY"]), Convert.ToDouble(dataTable.Rows[0]["PtZ"]));
                    DBService.SectionType sectionType = (DBService.SectionType)Convert.ToInt32(dataTable.Rows[0]["SectionType"]);
					SectionParameter sp = null;
                    if (sectionType == DBService.SectionType.Arc)
					{
						sp = new SectionParameter(Convert.ToDouble(dataTable.Rows[0]["Parameter1"]));
					}
                    else if (sectionType == DBService.SectionType.Rect)
					{
						double param = Convert.ToDouble(dataTable.Rows[0]["Parameter1"]);
						double param2 = Convert.ToDouble(dataTable.Rows[0]["Parameter2"]);
						sp = new SectionParameter(param, param2);
					}
                    DBService.SectionType sectionType2 = (DBService.SectionType)Convert.ToInt32(dataTable.Rows[0]["BoxSectionType"]);
					BoxParameter bp = null;
                    if (sectionType2 == DBService.SectionType.Arc)
					{
						bp = new BoxParameter(Convert.ToDouble(dataTable.Rows[0]["BoxParameter1"]));
					}
                    else if (sectionType2 == DBService.SectionType.Rect)
					{
						double param3 = Convert.ToDouble(dataTable.Rows[0]["BoxParameter1"]);
						double param4 = Convert.ToDouble(dataTable.Rows[0]["BoxParameter1"]);
						double param5 = Convert.ToDouble(dataTable.Rows[0]["BoxParameter3"]);
						double param6 = Convert.ToDouble(dataTable.Rows[0]["BoxParameter4"]);
						bp = new BoxParameter(param3, param4, param5, param6);
					}
					CutType cType = (CutType)Convert.ToInt32(dataTable.Rows[0]["CutType"]);
					HostType hType = (HostType)Convert.ToInt32(dataTable.Rows[0]["HostType"]);
					string level = Convert.ToString(dataTable.Rows[0]["Level"]);
					string remark = Convert.ToString(dataTable.Rows[0]["Remark"]);
					result = new DbBeamToBeOpened(projectId, basePt, beamId, pipeId, sp, bp, cType, hType, level)
					{
						Remark = remark,
						mGuid = id,
						mDatabase = db,
						Status = status
					};
				}
			}
			catch (Exception ex)
			{
				if (db.Connection.State == ConnectionState.Open)
				{
					db.Connection.Close();
				}
				throw ex;
			}
			return result;
		}

		public override bool Equals(object obj)
		{
			if (obj is DbBeamToBeOpened)
			{
				DbBeamToBeOpened dbBeamToBeOpened = (DbBeamToBeOpened)obj;
				return dbBeamToBeOpened.mPt.IsAlmostEqualTo(this.mPt) && dbBeamToBeOpened.mHostId == this.mHostId;
			}
			return false;
		}
	}
}
